#pragma once
#include<iostream>
#include<cstring>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<functional>
#include"log.hpp"

namespace USV
{
    using func_t=std::function<std::string(std::string)>;
    #define defaultfd -1
    class UdpServer
    {
        public:
        UdpServer(uint16_t port,func_t func)
        :_sockfd(defaultfd)
        ,_func(func)
        ,_port(port)
        {}
        void Init()
        {
            //创建网络文件（套接字）
            _sockfd=socket(AF_INET,SOCK_DGRAM,0);
            if(_sockfd<0)
            {
                LOG(LogLevel::ERROR)<<"socket fail!";
                exit(1);
            }
            LOG(LogLevel::INFO)<<"socket success!";
            //std::cout<<"socket success!"<<std::endl;
            //给socket绑定ip与端口
            struct sockaddr_in local;
            bzero(&local,sizeof(local));
            local.sin_family=AF_INET;
            local.sin_port=htons(_port);
            //4字节IP
            local.sin_addr.s_addr=INADDR_ANY;

            //绑定
            int ret=bind(_sockfd,(const struct sockaddr*)&local,sizeof(local));
            if(ret<0)
            {
                LOG(LogLevel::ERROR)<<"bind fail!";
                exit(2);
            }
            LOG(LogLevel::INFO)<<"bind success!";
        }
        void Start()
        {
            _isrunning=true;
            
            while(_isrunning)
            {
                //自定义缓冲区：
                char buffer[1024];
                //输出型函数用来保存客户端的ip与端口
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);//返回时是实际读取的大小
                ssize_t n=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
                if(n>0)
                {
                    //接受到了客户端发来的数据
                    buffer[n]='0';

                    std::string messager=_func(buffer);

                    sendto(_sockfd,messager.c_str(),messager.size(),0,(struct sockaddr*)&peer,len);
                }
            }
        }
        ~UdpServer()
        {}
        private:
        int _sockfd;
        uint16_t _port;

        func_t _func;
        bool _isrunning;
    };
}
